Micron Document
🎖️GitЯра🎖️

Node / meshtastic / Meshtastic-Android / files / docs / decisions / koin-migration.md

Displaying Raw • View renderedDownload

docs/decisions/koin-migration.md copilot/create-implementation-plan (228d872f) Text, 2.08 KB

Tc9d1d9# Decision: Hilt → Koin Migration

Tff7b72> Date: 2026-02-20 to 2026-03-09 | Status: **Complete**

Tc9d1d9## Context

Hilt (Dagger) was the strongest remaining barrier to KMP adoption — it requires Android-specific annotation processing and can't run in Ta5d6ff`commonMain`.

Tc9d1d9## Decision

Migrated to **Koin 4.2.0-RC1** with the **K2 Compiler Plugin** (Ta5d6ff`io.insert-koin.compiler.plugin`) and later upgraded to **0.4.1**.

Key choices:
Tff7b72- Ta5d6ff`@KoinViewModel` replaces Ta5d6ff`@HiltViewModel`; Ta5d6ff`koinViewModel()` replaces Ta5d6ff`hiltViewModel()`
Tff7b72- Ta5d6ff`@Module` + Ta5d6ff`@ComponentScan` in Ta5d6ff`commonMain` modules (valid 2026 KMP pattern)
Tff7b72- Ta5d6ff`@KoinWorker` replaces Ta5d6ff`@HiltWorker` for WorkManager
Tff7b72- Ta5d6ff`@InjectedParam` replaces Ta5d6ff`@Assisted` for factory patterns
Tff7b72- Root graph assembly centralized in Ta5d6ff`AppKoinModule`; shared modules expose annotated definitions
Tff7b72- **Koin 0.4.1 A1 Compile Safety Disabled:** Meshtastic heavily utilizes dependency inversion across KMP modules (e.g., interfaces defined in Ta5d6ff`core:repository` are implemented in Ta5d6ff`core:data`). Koin 0.4.x's per-module A1 validation strictly enforces that all dependencies must be explicitly provided or included locally, breaking this clean architecture. We have globally disabled A1 Ta5d6ff`compileSafety` in Ta5d6ff`KoinConventionPlugin` to properly rely on Koin's A3 full-graph validation at the composition root (Ta5d6ff`startKoin`).

Tc9d1d9## Gotchas Discovered

Tff7b721. **K2 Compiler Plugin signature collision:** Multiple Ta5d6ff`@Single` providers with identical JVM signatures in the same Ta5d6ff`@Module` cause Ta5d6ff`ClassCastException`. Fix: split into separate Ta5d6ff`@Module` classes.
Tff7b722. **Circular dependencies:** Ta5d6ff`Lazy<T>` injection can still Ta5d6ff`StackOverflowError` if Ta5d6ff`Lazy` is accessed too early (e.g., in Ta5d6ff`init` coroutine). Fix: pass dependencies as function parameters instead.
Tff7b723. **Robolectric `KoinApplicationAlreadyStartedException`:** Call Ta5d6ff`stopKoin()` in Ta5d6ff`onTerminate`.

Tc9d1d9## Consequences

Tff7b72- Hilt completely removed
Tff7b72- All 23 KMP modules can contain Koin-annotated definitions
Tff7b72- Desktop bootstraps its own Ta5d6ff`DesktopKoinModule` with stubs + real implementations
Tff7b72- 11 passthrough Android ViewModel wrappers eliminated

Served by rngit 1.5.0 - Generated in 0.04s